﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Controller;
using ICSharpCode.TextEditor;
using ICSharpCode.TextEditor.Document;
using System.Xml;
using Common;
using DevExpress.XtraTreeList;
using DevExpress.XtraTreeList.Nodes;
using Model;

namespace CodeFactory
{
    public partial class CodeShop : Form
    {
        public CodeShop()
        {
            InitializeComponent();
        }

        /// <summary>
        /// 初始化时传入调用者代码
        /// </summary>
        /// <param name="_whoCallThisBox">
        /// 0主页调用，用于管理代码
        /// 1从模板新建方法
        /// 2往现存方法中添加代码
        /// </param>
        public CodeShop(enumWhoCallCodeShop _whoCallTheBox)
        {
            InitializeComponent();
            whoCallTheBox = _whoCallTheBox;
        }



        /// <summary>
        /// 初始化时传入调用者代码
        /// </summary>       
        /// <param name="_cpg"></param>
        /// <param name="_whoCallThisBox">
        /// 0主页调用，用于管理代码
        /// 1从模板新建方法
        /// 2往现存方法中添加代码
        /// </param>
 
        public CodeShop(CustomPropertyGrid _cpg, enumWhoCallCodeShop _whoCallTheBox)
        {
            InitializeComponent();
            whoCallTheBox = _whoCallTheBox;
            cpg = _cpg;
        }
        
        private CodeFactaryBO _CFBO;
        public CodeFactaryBO CFBO
        {
            get
            {
                if (_CFBO == null)
                    _CFBO = FactoryControllerBO.CurrentFA.CreateCodeFactaryBOInstance();
                return _CFBO;
            }
        }


        #region 复制粘贴

        private void copyToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (HaveSelection())
                DoEditAction(txtCode, new ICSharpCode.TextEditor.Actions.Copy());
        }

        private void cutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            DoEditAction(txtCode, new ICSharpCode.TextEditor.Actions.Paste());
        }

        private void pasteToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (HaveSelection())
                DoEditAction(txtCode, new ICSharpCode.TextEditor.Actions.Cut());
        }

        private void DoEditAction(TextEditorControl editor, ICSharpCode.TextEditor.Actions.IEditAction action)
        {
            if (editor != null && action != null)
            {
                var area = editor.ActiveTextAreaControl.TextArea;
                editor.BeginUpdate();
                try
                {
                    lock (editor.Document)
                    {
                        action.Execute(area);
                        if (area.SelectionManager.HasSomethingSelected && area.AutoClearSelection /*&& caretchanged*/)
                        {
                            if (area.Document.TextEditorProperties.DocumentSelectionMode == DocumentSelectionMode.Normal)
                            {
                                area.SelectionManager.ClearSelection();
                            }
                        }
                    }
                }
                finally
                {
                    editor.EndUpdate();
                    area.Caret.UpdateCaretPosition();
                }
            }
        }

        private bool HaveSelection()
        {
            var editor = txtCode;
            return editor != null &&
                editor.ActiveTextAreaControl.TextArea.SelectionManager.HasSomethingSelected;
        }

        #endregion


        private void CodeFactary_Load(object sender, EventArgs e)
        {
            SetBottomButtonShow(whoCallTheBox);

            CFBO.LoadConfig(treeMenu);

            txtCode.Document.DocumentChanged += new DocumentEventHandler(txtCode_DocumentChanged);

            treeMenu.ExpandAll();
        }

        #region 字段，属性

        bool IsFromMainWindow=true;

        enumWhoCallCodeShop whoCallTheBox;

        CustomPropertyGrid cpg;

        int num; 

        #endregion



        #region 方法

        public bool AddNewMethod(eProperty ep)
        {
            if(HasSameName(ep.Name))
            {
                return false;
            }
            else
            {
                TreeListNode tln = null;
                if (treeMenu.Selection[0]["Type"].ToString() == enumCodeShopType.Method.ToString())
                {
                     tln= treeMenu.AppendNode(null, treeMenu.Selection[0].ParentNode.Id);
                }
                else if (treeMenu.Selection[0]["Type"].ToString() == enumCodeShopType.Folder.ToString())
                {
                    tln = treeMenu.AppendNode(null, treeMenu.Selection[0].Id);
                }

                tln.SetValue("Type", enumCodeShopType.Method);
                tln.SetValue("Name",ep.Name);
                tln.SetValue("ReturnType",ep.ReturnType);
                tln.SetValue("Accessibility", ep.Accessibility);
                tln.SetValue("Code", "");

                if (ep.ParamList.Count>0)
                {
                    StringBuilder sb = new StringBuilder();
                    foreach (eMethodParam mp in ep.ParamList)
                    {
                        if (!String.IsNullOrEmpty(mp.OutputType) && mp.OutputType != "none")
                        {
                            sb.Append(mp.OutputType);
                            sb.Append(" ");
                        }
                        sb.Append(mp.DataType);
                        sb.Append(" ");
                        sb.Append(mp.ParamName);
                        sb.Append(",");
                    }
                    sb.Remove(sb.Length - 1, 1);//去掉最后一个逗号

                    tln.SetValue("Param", sb.ToString());
                }
                else
                {
                    tln.SetValue("Param", "");
                }
                return true;
            }
        }

        public void AddNewFolder(string name)
        {
            TreeListNode tln = treeMenu.AppendNode(null, null);
            tln.SetValue("Name", name);
            tln.SetValue("Type", enumCodeShopType.Folder);
        }

        public bool HasSameFolder(string name)
        {
            if (treeMenu.FindNodeByFieldValue("Name", name) == null)
            {
                return false;
            }
            else
            {
                return true;
            }
        }

        public bool HasSameName(string name)
        {
            num = 0;
            string oldname = treeMenu.Selection[0].GetValue("Name").ToString();
            treeMenu.Selection[0].SetValue("Name", txtMethod.Text.Trim());
            foreach (TreeListNode tln in treeMenu.Nodes)
            {
                ErgodicAllNode(tln, name);
            }
            treeMenu.Selection[0].SetValue("Name", oldname);
            if (num > 1)
            {
                return true;
            }
            else
            {
                return false;
            }
        }


        private void SetBottomButtonShow(enumWhoCallCodeShop _whoCall)
        {
            if (_whoCall==enumWhoCallCodeShop.MainForm)
            {
                btnCancel.Visible = false;
                btnOK.Visible = false;
                btnClose.Visible = true;
            }
            else
            {
                btnCancel.Visible = true;
                btnOK.Visible = true;
                btnClose.Visible = false;
            }
        }

        /// <summary>
        /// 递归查找每个子节点
        /// </summary>
        /// <param name="tln"></param>
        /// <param name="name"></param>
        private void ErgodicAllNode(TreeListNode tln, string name)
        {
            if (tln.GetValue("Name").ToString() == name)
            {
                num++;
            }
            if (tln.HasChildren)
            {
                foreach (TreeListNode tlnChild in tln.Nodes)
                {
                    ErgodicAllNode(tlnChild, name);
                }
            }
        } 

        #endregion


        #region 事件
   
        private void treeMenu_MouseClick(object sender, MouseEventArgs e)
        {
            TreeListHitInfo hitinfo = new TreeListHitInfo();
            hitinfo = treeMenu.CalcHitInfo(new Point(e.X, e.Y));

            //if mouse not click the nodes, do nothing;
            if (hitinfo.HitInfoType != HitInfoType.Cell)
            {
                return;
            }
            if (e.Button != MouseButtons.Left)
            {
                return;
            }
            if (treeMenu.Nodes.Count < 1)
            {
                return;
            }
            try
            {

                if (treeMenu.Selection[0]["Type"].ToString() == enumCodeShopType.Method.ToString())
                {
                    txtReturnType.Text = treeMenu.Selection[0]["ReturnType"].ToString();
                    txtMethod.Text = treeMenu.Selection[0]["Name"].ToString();
                    txtParam.Text = treeMenu.Selection[0]["Param"].ToString();
                    txtAccessibility.Text = treeMenu.Selection[0]["Accessibility"].ToString();
                    txtCode.SetHighlighting("C#");
                    txtCode.Text = treeMenu.Selection[0]["Code"].ToString();
                    txtCode.Refresh();
                }
                else
                {
                    txtAccessibility.Text = "";
                    txtReturnType.Text = "";
                    txtMethod.Text = treeMenu.Selection[0]["Name"].ToString();
                    txtParam.Text = "";
                    txtCode.Text = String.Empty;
                    txtCode.Refresh();
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        private void txtReturnType_TextChanged(object sender, EventArgs e)
        {
            if (treeMenu.Selection.Count > 0 && treeMenu.Selection[0]["Type"].ToString() == enumCodeShopType.Method.ToString())
            {
                treeMenu.Selection[0].SetValue("ReturnType", txtReturnType.Text.Trim());
            }
        }

        private void txtParam_TextChanged(object sender, EventArgs e)
        {
            if (treeMenu.Selection.Count > 0 && treeMenu.Selection[0]["Type"].ToString() == enumCodeShopType.Method.ToString())
            {
                treeMenu.Selection[0].SetValue("Param", txtParam.Text.Trim());
            }
        }

        private void txtAccessibility_TextChanged(object sender, EventArgs e)
        {
            if (treeMenu.Selection.Count > 0 && treeMenu.Selection[0]["Type"].ToString() == enumCodeShopType.Method.ToString())
            {
                treeMenu.Selection[0].SetValue("Accessibility", txtAccessibility.Text.Trim());
            }
        }

        private void txtCode_DocumentChanged(object sender, EventArgs e)
        {
            if (treeMenu.Selection.Count > 0 && treeMenu.Selection[0]["Type"].ToString() == enumCodeShopType.Method.ToString())
            {
                treeMenu.Selection[0].SetValue("Code", txtCode.Text);
            }
        }

        private void txtMethod_Leave(object sender, EventArgs e)
        {
            if (treeMenu.Selection.Count > 0)
            {
                if (HasSameName(txtMethod.Text.Trim()))
                {
                    MessageBox.Show("已存在相同名称,在修改之前无法保存");
                }
                else
                {
                    treeMenu.Selection[0].SetValue("Name", txtMethod.Text.Trim());
                }
            }
        } 

        #endregion


        #region 按钮
        
        /// <summary>
        /// 新类别
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tsBtnNewFolder_Click(object sender, EventArgs e)
        {
            using (CodeShopNewFolder cf = new CodeShopNewFolder()) 
            {
                cf.HasSameFolder += HasSameFolder;
                cf.AddNewFolder += AddNewFolder;
                cf.ShowDialog();
            }
        }   

        /// <summary>
        /// 保存代码
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tsSaveCode_Click(object sender, EventArgs e)
        {
            if (treeMenu.Selection.Count > 0)
            {
                if (HasSameName(txtMethod.Text.Trim()))
                {
                    MessageBox.Show("已存在相同名称，在修改之前无法保存");
                    return;
                }
                else
                {
                    treeMenu.Selection[0].SetValue("Name", txtMethod.Text.Trim());
                }
            }

            CFBO.SaveConfig(treeMenu);
            MessageBox.Show("代码保存成功！");
        }
     

        /// <summary>
        /// 确定提交×××××××××××××××××××××××××××××××××××
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnOK_Click(object sender, EventArgs e)
        {
            if(treeMenu.Selection.Count==0)
            {
                MessageBox.Show("请先选一个要返回的方法");
                return;
            }
            if(treeMenu.Selection[0]["Type"].ToString()==enumCodeShopType.Folder.ToString())
            {
                MessageBox.Show("请选一个方法而不是目录");
                return;
            }

            eProperty ep = null;
            switch (whoCallTheBox)
            {
                
                case enumWhoCallCodeShop.MethodForCode:
                    ep = new eProperty();
                    ep.Value = treeMenu.Selection[0]["Code"].ToString();
                    cpg.AddMethodCodeToTree(ep);
                    break;
                
                case enumWhoCallCodeShop.MethodFromTemplate:

                    ep = new eProperty();
                    ep.Accessibility=treeMenu.Selection[0]["Accessibility"].ToString();
                    ep.Name=treeMenu.Selection[0]["Name"].ToString();
                    ep.PropertyType=enumPropertyType.Method;
                    ep.ReturnType=treeMenu.Selection[0]["ReturnType"].ToString();
                    ep.Value=treeMenu.Selection[0]["Code"].ToString();
                    ep.ValueType = "Method";
                    ep.Accessibility=treeMenu.Selection[0]["Accessibility"].ToString();
                    
                    List<eMethodParam> listParam = new List<eMethodParam>();

                    try
                    {
                        foreach (string param in treeMenu.Selection[0]["Param"].ToString().Split(','))
                        {
                            //排除掉空字符
                            List<string> list = new List<string>();
                            foreach (string s in param.Split(' '))
                            {
                                if (!String.IsNullOrEmpty(s))
                                {
                                    list.Add(s);
                                }
                            }

                            eMethodParam mp = new eMethodParam();
                            if (list.Count > 2)
                            {
                                mp.OutputType = list[0];
                                mp.DataType = list[1];
                                mp.ParamName = list[2];
                            }
                            else
                            {
                                mp.OutputType = "none";
                                mp.DataType = list[0];
                                mp.ParamName = list[1];
                            }

                            listParam.Add(mp);
                        }
                    }
                    catch(Exception ex)
                    {
                        
                        throw ex;
                    }
                    ep.ParamList = listParam;
                    
                    cpg.AddMethodsToTree(ep);
                
                    break;
            }
            Close();
        }


        /// <summary>
        /// 取消
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnCancel_Click(object sender, EventArgs e)
        {
            try
            {
                Close();
            }
            finally
            {
                if (!this.IsDisposed)
                    Dispose();
            } 
        } 

        /// <summary>
        /// 关闭窗口
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void CodeFactary_FormClosed(object sender, FormClosedEventArgs e)
        {
            if (!this.IsDisposed)
                Dispose();
        }

        /// <summary>
        /// 关闭窗口
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnClose_Click(object sender, EventArgs e)
        {
            try
            {
                Close();
            }
            finally
            {
                if (!this.IsDisposed)
                Dispose();
            }
        }
        #endregion

        private void tsBtnNewCode_Click(object sender, EventArgs e)
        {
            if (treeMenu.Selection.Count == 0)
            {
                MessageBox.Show("请先选中一个分类！");
            }
            else
            {
                using (MethodFieldCreater mfc = new MethodFieldCreater(this, true))
                {
                    mfc.ShowDialog();
                }
            }
        }

        private void tsBtnShowAll_Click(object sender, EventArgs e)
        {
            treeMenu.ExpandAll();
        }

        private void tsBtnHideAll_Click(object sender, EventArgs e)
        {
           treeMenu.CollapseAll(); 
        }
      

    }
}
